deploy: Delete .updated file from /etc and /var on new deployments
authorDan Nicholson <nicholson@endlessm.com>
Sat, 25 Jul 2015 16:51:14 +0000 (09:51 -0700)
committerAtomic Bot <atomic-devel@projectatomic.io>
Mon, 18 Jun 2018 13:21:52 +0000 (13:21 +0000)
Systemd units using ConditionNeedsUpdate run if the mtime of .updated in
the specified directory is newer than /usr. Since /usr has an mtime of
0, there's no way to have an older .updated file. Systemd units
typically specify ConditionNeedsUpdate=/etc or ConditionNeedsUpdate=/var
to support stateless systems like ostree.

Remove the file from the new deployment's /etc and the OS's /var
regardless of where they came from to ensure that these systemd units
run when booting new deployments. This will provide a method to run
services only on upgrade.

Closes: #1628
https://bugzilla.gnome.org/show_bug.cgi?id=752950

Closes: #1631
Approved by: cgwalters

Makefile-tests.am
src/libostree/ostree-sysroot-deploy.c
tests/test-admin-upgrade-systemd-update.sh [new file with mode: 0755]

index 97a71d0dea9561bfe3445c7ffc6d96ab9a945a53..85995aa6ee3f0b8a58dbc24932b7d6298408bcd4 100644 (file)
@@ -94,6 +94,7 @@ _installed_or_uninstalled_test_scripts = \
        tests/test-gpg-signed-commit.sh \
        tests/test-admin-upgrade-unconfigured.sh \
        tests/test-admin-upgrade-endoflife.sh \
+       tests/test-admin-upgrade-systemd-update.sh \
        tests/test-admin-deploy-syslinux.sh \
        tests/test-admin-deploy-2.sh \
        tests/test-admin-deploy-karg.sh \
index 6f0f6efd93cc4385edff6cb9e50f90f7ba862814..08bf4c0d0a19ef3ec6819f01e8b0e63ec7c02591 100644 (file)
@@ -684,15 +684,10 @@ selinux_relabel_dir (OstreeSysroot                 *sysroot,
 static gboolean
 selinux_relabel_var_if_needed (OstreeSysroot                 *sysroot,
                                OstreeSePolicy                *sepolicy,
-                               OstreeDeployment              *deployment,
+                               int                            os_deploy_dfd,
                                GCancellable                  *cancellable,
                                GError                       **error)
 {
-  const char *osdeploypath = glnx_strjoina ("ostree/deploy/", ostree_deployment_get_osname (deployment));
-  glnx_autofd int os_deploy_dfd = -1;
-  if (!glnx_opendirat (sysroot->sysroot_fd, osdeploypath, TRUE, &os_deploy_dfd, error))
-    return FALSE;
-
   /* This is a bit of a hack; we should change the code at some
    * point in the distant future to only create (and label) /var
    * when doing a deployment.
@@ -2529,11 +2524,25 @@ sysroot_finalize_deployment (OstreeSysroot     *self,
         return FALSE;
     }
 
+  const char *osdeploypath = glnx_strjoina ("ostree/deploy/", ostree_deployment_get_osname (deployment));
+  glnx_autofd int os_deploy_dfd = -1;
+  if (!glnx_opendirat (self->sysroot_fd, osdeploypath, TRUE, &os_deploy_dfd, error))
+    return FALSE;
+
+  /* Ensure that the new deployment does not have /etc/.updated or
+   * /var/.updated so that systemd ConditionNeedsUpdate=/etc|/var services run
+   * after rebooting.
+   */
+  if (!ot_ensure_unlinked_at (deployment_dfd, "etc/.updated", error))
+    return FALSE;
+  if (!ot_ensure_unlinked_at (os_deploy_dfd, "var/.updated", error))
+    return FALSE;
+
   g_autoptr(OstreeSePolicy) sepolicy = ostree_sepolicy_new_at (deployment_dfd, cancellable, error);
   if (!sepolicy)
     return FALSE;
 
-  if (!selinux_relabel_var_if_needed (self, sepolicy, deployment, cancellable, error))
+  if (!selinux_relabel_var_if_needed (self, sepolicy, os_deploy_dfd, cancellable, error))
     return FALSE;
 
   /* Rewrite the origin using the final merged selinux config, just to be
diff --git a/tests/test-admin-upgrade-systemd-update.sh b/tests/test-admin-upgrade-systemd-update.sh
new file mode 100755 (executable)
index 0000000..94b750d
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/bash
+#
+# Copyright (C) 2014 Colin Walters <walters@verbum.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+set -euo pipefail
+
+. $(dirname $0)/libtest.sh
+
+# Exports OSTREE_SYSROOT so --sysroot not needed.
+setup_os_repository "archive-z2" "syslinux"
+
+echo "1..2"
+
+# Setup a deployment
+cd ${test_tmpdir}
+${CMD_PREFIX} ostree --repo=sysroot/ostree/repo remote add --set=gpg-verify=false testos $(cat httpd-address)/ostree/testos-repo
+${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull testos testos/buildmaster/x86_64-runtime
+rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
+${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmaster/x86_64-runtime
+assert_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0/usr
+assert_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0/etc
+assert_has_dir sysroot/ostree/deploy/testos/var
+assert_not_has_file sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/.updated
+assert_not_has_file sysroot/ostree/deploy/testos/var/.updated
+
+echo "ok deploy"
+
+# Create the /etc/.updated and /var/.updated files with /usr modification time
+usr=sysroot/ostree/deploy/testos/deploy/${rev}.0/usr
+touch -r ${usr} sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/.updated
+touch -r ${usr} sysroot/ostree/deploy/testos/var/.updated
+
+# Make a new commit, upgrade and ensure .updated files are gone in the
+# new deployment but /etc/.updated still exists in the previous
+# (current) deployment
+os_repository_new_commit
+${CMD_PREFIX} ostree admin upgrade --os=testos
+newrev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
+assert_not_has_file sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/.updated
+assert_not_has_file sysroot/ostree/deploy/testos/var/.updated
+assert_has_file sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/.updated
+
+echo "ok .updated files removed"